#include "stdafx.h"
#include "TestSystem.h"

namespace Nezha
{
	void NZTestPerUpdateSampler::reportAllSamples()
	{
		for(PArray<NZTestSample>::iterator it = mSamples.begin(); it != mSamples.end(); it++)
		{
			reportSample((*it));
		}

		mSamples.clear();
	}

	void NZTestPerUpdateSampler::reportSample(const NZTestSample& s)
	{
		//
		printf("Sample %d cost time %d ms\n", s.SampleIndex, s.Ticks);
	}

	bool NZTest::initialize()
	{
		if(mPerUpdateSampler)
		{
			mPerUpdateSampler->prepare();
		}

		// tempory
		printf("Test %s start\n", mName.c_str());

		return true;
	}

	void NZTest::uninitialize()
	{
		// tempory
		printf("Test %s end\n", mName.c_str());

		if(mPerUpdateSampler)
		{
			mPerUpdateSampler->reportAllSamples();
		}
	}

	void TestSystem::initializeFromCfg(const _string& fileName)
	{
		// TODO
	}

	void TestSystem::registerFacoty(TestFactory* fac)
	{
		if(!fac)
		{
			return;
		}

		PMap<_string, TestFactoryPtr>::iterator it = mFacoties.find(fac->getName());
		if(it == mFacoties.end())
		{
			TestFactoryPtr ptr(fac);
			mFacoties.insert(std::pair<_string, TestFactoryPtr>(fac->getName(), ptr));
		}
	}

	void TestSystem::addTest(const _string& testName, u32 testTimes /* = 1 */)
	{
		PMap<_string, TestFactoryPtr>::iterator it = mFacoties.find(testName);
		if(it != mFacoties.end())
		{
			addTest(it->second->create(), testTimes);
		}
	}

	void TestSystem::addTest(NZTest* t, u32 times)
	{
		if(!t || t->isTesting() || times == 0)
		{
			return;
		}

		NZTestPtr ptr(t);
		t->mTestCounter = times;
		mWaitingQueue.push_back(ptr);
	}

	void TestSystem::update(float dt)
	{
		if(mCurrentTest.isNull())
		{
			NZTest* prev = NULL;
			for(PArray<NZTestPtr>::iterator it = mWaitingQueue.begin(); it != mWaitingQueue.end(); it++)
			{
				if(prev)
				{
					prev->mNext = (*it);
				}
				else
				{
					mCurrentTest = (*it);
				}

				prev = (*it).get();
			}

			mWaitingQueue.clear();

			if(mCurrentTest.get())
			{
				while(!mCurrentTest->initialize())
				{
					mCurrentTest->uninitialize();

					// for smart pointer, we can't assgin like lhs = rhs->next, it's dangerous.
					NZTestPtr next = mCurrentTest->mNext;
					mCurrentTest = next;
				}

				mCurrentTest->mTesting = true;
			}
		}
		else
		{
			if(mCurrentTest->update(dt))
			{
				if(--mCurrentTest->mTestCounter > 0)
				{
					mCurrentTest->reset();
				}
				else
				{
					mCurrentTest->mTesting = false;
					mCurrentTest->uninitialize();

					NZTestPtr next = mCurrentTest->mNext;
					mCurrentTest = next;

					if(mCurrentTest.get())
					{
						while(!mCurrentTest->initialize())
						{
							mCurrentTest->uninitialize();
							mCurrentTest = mCurrentTest->mNext;
						}

						mCurrentTest->mTesting = true;
					}
				}
			}
		}
	}

	void TestSystem::randomizeEnglishString(_string& str, u16 maxLen)
	{
		if(maxLen < 3)
			maxLen = 3;

		u16 _len = 3;
		if(maxLen > 3)
			_len += NZRand() % (maxLen - 3);

		str.clear();
		str.resize(_len + 1, 0);

		// 48 - 57
		// 65 - 90
		// 97 - 122
		for(u16 i = 0; i < _len; i++)
		{
			int n = NZRand() % 3;
			if(n == 0)
			{
				str[i] = (char)NZRandom::Rangei(48, 58);
			}
			else if(n == 1)
			{
				str[i] = (char)NZRandom::Rangei(65, 91);
			}
			else
			{
				str[i] = (char)NZRandom::Rangei(97, 123);
			}
		}

		str[_len] = 0;
	}
}